Naught Coin
1. 题目要求
1.1 NaughtCoin 是一种 ERC20 代币,而且您已经持有这些代币。问题是您只能在 10 年之后才能转移它们。您能尝试将它们转移到另一个地址,以便您可以自由使用它们吗?通过将您的代币余额变为 0 来完成此关卡。
这可能有用
1.2 题目代码:
1 | // SPDX-License-Identifier: MIT |
2. 分析
2.1 通过让您的代币余额为 0 来完成此级别
2.2 ***tips:**在
*constructor*
*.*_mint*
在执行合约*emit*
事件**后*Transfer*
,不知道 OpenZeppelin*_mint*
函数的本机实现已经是*emit*
事件*Transfer*
要解决这个合约,我们需要知道 ERC20 代币的 EIP(以太坊改进提案)是如何工作的,以及 OpenZeppelin 是如何实现它的(该合约使用的是 OpenZeppelin 框架库)。
您可以从这些链接中找到所需的所有信息:
转移代币有两种方式:
- 通过
transfer
允许msg.sender
直接将代币转移到recipient
- 通过
transferFrom
允许外部任意sender
(可能是代币本身的所有者)代表所有者将amount
代币转移到recipient
. 在发送这些代币之前,所有者必须已批准管理sender
该数量的代币
因为
transfer
方法已经overrided
约定好了NaughtCoin
,我们可以使用函数来规避限制transferFrom
。这是我们需要做的:
- 创建一个二级账户,将我们所有的代币转移到 2) 在调用之前批准我们自己管理全部代币
transferFrom
3) 调用transferFrom(player, secondaryAccount, token.balanceOf(player))
4) 随心所欲地使用代币!
1
NaughtCoin`合约应该实施什么才能真正锁定我们的代币**10 年**?他们可以实现EIP-20 定义的**一个挂钩**`overriding`,称为.`transfer``_beforeTokenTransfer
当发生任何类型的令牌传输时,将调用此挂钩:
mint
(从地址转移0x
到用户)burn
(从用户转移到0x
地址)transfer
transferFrom
通过这样做,他们可以防止这种利用。
- 通过
2.3 参考视频 写的攻击合约
interface INaughtCoin { function player() external view returns (address); } contract Hack { function pwn(IERC20 coin) external { address player = INaughtCoin(address(coin)).player(); uint bal = coin.balanceOf(player); coin.transferFrom(player, address(this), bal); } }
1
2
3
4
5
6
7
- 2.4 解题步骤为:
- ```
// 1.Deploy
// 2.coin.approve(hack, amount)
// 3.pwn()
3. 解题
- 3.1 获取关卡实例地址:0x34df3070B62B46bCBc4d0a2cbCcd670109041b8a
- 3.2 部署攻击合约 Hack
- 3.3 根据关卡实例地址 生成 IECR20 合约
- 3.4 调用IECR20 合约中的balanceOf() 函数查看当前账户余额
- 3.5 再调用IECR20 合约的approve() 函数,传入Hack 合约地址和 所查账户余额
- 3.6 调用Hack 合约中的pwn() 函数 传入关卡实例
- 3.7 回到IECR20 合约中调用balanceOf() 函数查看当前账户余额
- 3.8 提交实例
- 3.9 成功!!!!